﻿using Engine.TrafficHelpers;
using SharpDX;
using System.Collections.Generic;

namespace Engine.Graphics.RenderableObjects
{
    public class TrafficCrossroadMesh : IRenderableObject
    {
        #region Private Fields

        private Engine engine;
        private List<SplineGraphicsObject> splineGraphicObjects;

        #endregion Private Fields

        #region Public Constructors

        public TrafficCrossroadMesh(Engine engine)
        {
            this.engine = engine;
            this.splineGraphicObjects = new List<SplineGraphicsObject>();
        }

        #endregion Public Constructors

        #region Public Methods

        public void Dispose()
        {
            for (int i = 0; i < this.splineGraphicObjects.Count; i++)
            {
                this.splineGraphicObjects[i].Dispose();
            }
        }

        public void Render(int renderStep)
        {
            //this.engine.Device.SetRenderState(SharpDX.Direct3D9.RenderState.FillMode, SharpDX.Direct3D9.FillMode.Solid);
            for (int i = 0; i < this.splineGraphicObjects.Count; i++)
            {
                this.splineGraphicObjects[i].Render(renderStep);
            }
        }

        public void UpdateTraffic(CrossroadTraffic[] crossroadTraffic, Vector3 centerOfCross)
        {
            Dispose();
            this.splineGraphicObjects.Clear();

            if (crossroadTraffic.Length < 2)
                return;

            SortCrossroadTrafficByAngle(crossroadTraffic, centerOfCross);
            System.Drawing.Color colorLeft = System.Drawing.Color.Red;
            System.Drawing.Color colorForward = System.Drawing.Color.Green;
            System.Drawing.Color colorRight = System.Drawing.Color.Blue;
            for (int i = 0; i < crossroadTraffic.Length; i++)
            {
                System.Drawing.Color color = (crossroadTraffic[i].IsMainstreet) ? System.Drawing.Color.LightSeaGreen : System.Drawing.Color.Red;
                if (crossroadTraffic[i].LaneRight.Enable)
                {
                    color = colorRight;
                    Vector3[] middleLine = CreateMiddleLine(crossroadTraffic[i].LaneRight, i, GeoMath.GetNextId(i, crossroadTraffic.Length), crossroadTraffic);
                    splineGraphicObjects.Add(new SplineGraphicsObject(this.engine, crossroadTraffic[i].LaneRight.Lane.Offset1, middleLine, color));
                    if (crossroadTraffic[i].LaneRight.Lane.numberofLanes > 1)
                    {
                        middleLine = CreateMiddleLine(crossroadTraffic[i].LaneRight, i, GeoMath.GetNextId(i, crossroadTraffic.Length), crossroadTraffic);
                        splineGraphicObjects.Add(new SplineGraphicsObject(this.engine, crossroadTraffic[i].LaneRight.Lane.Offset2, middleLine, color));
                    }
                }

                if (crossroadTraffic.Length > 3 && crossroadTraffic[i].LaneForward.Enable)
                {
                    color = colorForward;
                    Vector3[] middleLine = CreateMiddleLine(crossroadTraffic[i].LaneForward, i, GeoMath.GetNextId(GeoMath.GetNextId(i, crossroadTraffic.Length), crossroadTraffic.Length), crossroadTraffic);
                    splineGraphicObjects.Add(new SplineGraphicsObject(this.engine, crossroadTraffic[i].LaneForward.Lane.Offset1, middleLine, color));
                    if (crossroadTraffic[i].LaneForward.Lane.numberofLanes > 1)
                    {
                        middleLine = CreateMiddleLine(crossroadTraffic[i].LaneForward, i, GeoMath.GetNextId(GeoMath.GetNextId(i, crossroadTraffic.Length), crossroadTraffic.Length), crossroadTraffic);
                        splineGraphicObjects.Add(new SplineGraphicsObject(this.engine, crossroadTraffic[i].LaneForward.Lane.Offset2, middleLine, color));
                    }
                }

                if (crossroadTraffic[i].LaneLeft.Enable)
                {
                    color = colorLeft;
                    Vector3[] middleLine = CreateMiddleLine(crossroadTraffic[i].LaneLeft, i, GeoMath.GetPreviousId(i, crossroadTraffic.Length), crossroadTraffic);
                    splineGraphicObjects.Add(new SplineGraphicsObject(this.engine, crossroadTraffic[i].LaneLeft.Lane.Offset1, middleLine, color));
                    if (crossroadTraffic[i].LaneLeft.Lane.numberofLanes > 1)
                    {
                        middleLine = CreateMiddleLine(crossroadTraffic[i].LaneLeft, i, GeoMath.GetPreviousId(i, crossroadTraffic.Length), crossroadTraffic);
                        splineGraphicObjects.Add(new SplineGraphicsObject(this.engine, crossroadTraffic[i].LaneLeft.Lane.Offset2, middleLine, color));
                    }
                }
            }
        }

        #endregion Public Methods

        #region Private Methods

        private Vector3[] CreateMiddleLine(CrossroadTrafficData crossroadTrafficData, int idStart, int idEnd, CrossroadTraffic[] crossroadTraffic)
        {
            Vector3[] startPoints = new Vector3[4];
            startPoints[0] = crossroadTraffic[idStart].StreetNode.Position - crossroadTraffic[idEnd].StreetNode.GetPositionFromTangent(crossroadTrafficData.TangentLengthEnd) * 15.0f;
            startPoints[1] = crossroadTraffic[idEnd].StreetNode.Position;
            startPoints[2] = crossroadTraffic[idStart].StreetNode.Position;
            startPoints[3] = crossroadTraffic[idEnd].StreetNode.Position - crossroadTraffic[idStart].StreetNode.GetPositionFromTangent(crossroadTrafficData.TangentLengthStart) * 15.0f;
            return GeoMath.CreateMiddleLine(startPoints, 10.0f);
        }

        private void SortCrossroadTrafficByAngle(CrossroadTraffic[] crossroadTraffic, Vector3 centerOfCrossroad)
        {
            bool sorted = true;
            do
            {
                sorted = true;
                for (int i = 0; i < crossroadTraffic.Length - 1; i++)
                {
                    double angle1 = GeoMath.GetXYAngel(centerOfCrossroad, crossroadTraffic[i].StreetNode.Position);
                    double angle2 = GeoMath.GetXYAngel(centerOfCrossroad, crossroadTraffic[i + 1].StreetNode.Position);

                    if (angle1 < angle2)
                    {
                        sorted = false;
                        CrossroadTraffic temp = crossroadTraffic[i];
                        crossroadTraffic[i] = crossroadTraffic[i + 1];
                        crossroadTraffic[i + 1] = temp;
                    }
                }
            } while (!sorted);
        }

        #endregion Private Methods
    }
}